package com.example.demo.stream.parallel;

import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.IntStream;

/**
 * @author MarioZzz
 * @create 2023-10-24 16:43
 */
@Slf4j
public class LockStream {
    /**
     * 采用stream的forEach接口对1-10000进行遍历，分别插入到3个ArrayList中。
     * 其中对第一个list的插入采用串行遍历，
     * 第二个使用parallelStream，
     * 第三个使用parallelStream的同时用ReentryLock对插入列表操作进行同步
     */
    private static List<Integer> list1 = new ArrayList<>();
    private static List<Integer> list2 = new ArrayList<>();
    private static List<Integer> list3 = new ArrayList<>();

    /**
     * 线程安全的List，底层用了ReentrantLock
     * 开销较大
     */
    private static CopyOnWriteArrayList<Integer> list4 = new CopyOnWriteArrayList<>();
    private static Lock lock = new ReentrantLock();

    public static void main(String[] args) {
        //开始时间
        long startTime = System.currentTimeMillis();

        IntStream.range(0, 10000).forEach(list1::add);
        long endTime1 = System.currentTimeMillis();

        IntStream.range(0, 10000).parallel().forEach(list2::add);
        long endTime2 = System.currentTimeMillis();

        /**
         * 锁的颗粒度很小时，对性能的影响很小
         */
        IntStream.range(0, 10000).parallel().forEach(i -> {
            lock.lock();
            try {
                list3.add(i);
            } finally {
                lock.unlock();
            }
        });
        long endTime3 = System.currentTimeMillis();

        IntStream.range(0, 10000).parallel().forEach(list4::add);
        long endTime4 = System.currentTimeMillis();

        log.info("串行执行的大小：{}，耗时：{}ms", list1.size(), (endTime1 - startTime));
        log.info("并行执行的大小：：{}，耗时：{}ms", list2.size(), (endTime2 - endTime1));
        log.info("加锁并行执行的大小：：{}，耗时：{}ms", list3.size(), (endTime3 - endTime2));
        log.info("CopyOnWriteArrayList执行的大小：：{}，耗时：{}ms", list4.size(), (endTime4 - endTime3));
    }
}
